package com.zone.mybatis.executor.resultset;

import com.zone.mybatis.io.Resources;
import com.zone.mybatis.mapping.BoundSql;

import java.lang.reflect.Method;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @author: zongzi
 * @description: TODO
 * @date: 2024/1/1
 */
public class DefaultResultSetHandler implements ResultSetHandler {
    private final BoundSql boundSql;

    public DefaultResultSetHandler(BoundSql boundSql) {
        this.boundSql = boundSql;
    }

    @Override
    public <E> List<E> handleResultSet(Statement statement) throws SQLException {
        ResultSet resultSet = statement.getResultSet();
        String resultTypeStr = boundSql.getResultType();
        try {
            return this.resultSetToObj(resultSet, Resources.classForName(resultTypeStr));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * ResultSet 转对象
     *
     * @param rs
     * @param clazz
     * @param <T>
     * @return
     */
    private <T> List<T> resultSetToObj(ResultSet rs, Class<?> clazz) throws Exception {
        List<T> resultList = new ArrayList<>();
        ResultSetMetaData metaData = rs.getMetaData();
        int columnCount = metaData.getColumnCount();
        T instance = (T) clazz.newInstance();
        while (rs.next()) {
            for (int i = 1; i <= columnCount; i++) {
                String columnName = metaData.getColumnName(i);
                String setMethodName = "set" + columnName.substring(0, 1).toUpperCase() + columnName.substring(1);

                Object value = rs.getObject(i);
                Method method;
                if (value instanceof Timestamp) {
                    method = clazz.getMethod(setMethodName, Date.class);
                } else {
                    method = clazz.getMethod(setMethodName, value.getClass());
                }
                method.invoke(instance, value);
            }
            resultList.add(instance);
        }
        return resultList;
    }
}
